package cn.com.doone.common.uc.oauth.shiro;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.HashSet;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.regex.Pattern;

import org.springframework.beans.factory.annotation.Value;

import cn.com.doone.common.uc.utils.StringUtils;
import redis.clients.jedis.HostAndPort;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisCluster;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;

public class RedisManager {
	
	private int expire = 0;

	public int getExpire() {
		return expire;
	}

	public void setExpire(int expire) {
		this.expire = expire;
	}
	
	@Value("${redis.auth}")
	private String auth;
	
	@Value("${redis.timeout:3000}")
	private int timeout;
	
	@Value("${redis.soTimeOut:3000}")
	private int soTimeOut;
	
	@Value("${redis.maxAttempts:5}")
	private int maxAttempts;
	
	private JedisCluster jedisCluster;
	private Pattern p = Pattern.compile("^.+[:]\\d{1,5}\\s*$");

	public RedisManager() throws IOException {
		
	}

	/**
	 * 初始化方法
	 * @throws Exception 
	 */
	public void init() throws Exception {
		String fileName = System.getProperty("catalina.base") + File.separator + "UcConfig" + File.separator + "uca"
				+ File.separator + "authz.properties";
		Properties prop = new Properties();
		try {
			prop.load(new FileInputStream(fileName));
		} catch (Exception e) {
			throw new FileNotFoundException("找不到配置文件");
		}
		
		JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
		jedisPoolConfig.setMaxIdle(5);
		jedisPoolConfig.setTestOnBorrow(false);
		jedisPoolConfig.setMaxWaitMillis(5000l);

		Set<HostAndPort> clusterNodes = new HashSet<HostAndPort>();
		for(Object key:prop.keySet()) {
			if(key.toString().indexOf("redis.address")<0) {
				continue;
			}
			String val = prop.get(key).toString();
			boolean isIpPort = p.matcher(val).matches();
			if (!isIpPort) {
                throw new IllegalArgumentException("ip 或 port 不合法");
            }
			String[] ipAndPort = val.split(":");
			HostAndPort hostAndPort = new HostAndPort(ipAndPort[0], Integer.parseInt(ipAndPort[1]));
			clusterNodes.add(hostAndPort);
		}
		
		if(StringUtils.isNull(auth)) {
			jedisCluster = new JedisCluster(clusterNodes, timeout, jedisPoolConfig);
		}else {
			jedisCluster = new JedisCluster(clusterNodes, timeout, soTimeOut, maxAttempts, auth, jedisPoolConfig);
		}
	}

	/**
	 * size
	 */
	@SuppressWarnings("deprecation")
	public Long dbSize() {
		return jedisCluster.dbSize();
	}

	/**
	 * del
	 * 
	 * @param key
	 */
	public void del(byte[] key) {
		jedisCluster.del(key);
	}

	/**
	 * del
	 * 
	 * @param key
	 */
	public void del(String key) {
		jedisCluster.del(key);
	}

	/**
	 * flush
	 */
	@SuppressWarnings("deprecation")
	public void flushDB() {
		Map<String, JedisPool> nodes = jedisCluster.getClusterNodes();
		for (Map.Entry<String, JedisPool> entry : nodes.entrySet()) {
			JedisPool jedisPool = entry.getValue();
			Jedis jedis = null;
			try {
				jedis = jedisPool.getResource();
			} catch (Exception e) {
				continue;
			} finally {
				jedisPool.returnResource(jedis);
			}
			jedis.flushDB();
		}
	}

	/**
	 * get value from redis
	 * 
	 * @param key
	 * @return
	 */
	public byte[] get(byte[] key) {
		return jedisCluster.get(key);
	}

	/**
	 * get value from redis
	 * 
	 * @param key
	 * @return
	 */
	public String get(String key) {
		return jedisCluster.get(key);
	}


	/**
	 * keys
	 * 
	 * @param regex
	 * @return
	 */
	public Set<byte[]> keys(String pattern) {
		return jedisCluster.hkeys(pattern.getBytes());

	}

	/**
	 * set
	 * 
	 * @param key
	 * @param value
	 * @return
	 */
	public byte[] set(byte[] key, byte[] value) {
		jedisCluster.set(key, value);
		if (this.expire != 0) {
			jedisCluster.expire(key, this.expire);
		}
		return value;
	}

	/**
	 * set
	 * 
	 * @param key
	 * @param value
	 * @param expire
	 * @return
	 */
	public byte[] set(byte[] key, byte[] value, int expire) {
		jedisCluster.set(key, value);
		if (expire != 0) {
			jedisCluster.expire(key, expire);
		}
		return value;
	}

	/**
	 * set
	 * 
	 * @param key
	 * @param value
	 * @return
	 */
	public String set(String key, String value) {
		jedisCluster.set(key, value);
		if (this.expire != 0) {
			jedisCluster.expire(key, this.expire);
		}
		return value;
	}

	/**
	 * set
	 * 
	 * @param key
	 * @param value
	 * @param expire
	 * @return
	 */
	public String set(String key, String value, int expire) {
		jedisCluster.set(key, value);
		if (expire != 0) {
			jedisCluster.expire(key, expire);
		}
		return value;
	}

}
